/********************************************************************
Crytek Source File.
Copyright (C), Crytek Studios, 2001-2008.
-------------------------------------------------------------------------
File name:   AIObjectsLogger.cpp
Description: Simple text AI event logger

-------------------------------------------------------------------------
History:
-01:07:2005 : Created by Kirill Bulatsev
-19:11:2008 : Separated out by Matthew
- 9.06.2011 : Renamed from CAIDbgRecorder to CAISystem::CAIActorsLogger by Evgeny Adamenkov

Notes:        Don't include the header in CAISystem - below it is redundant

*********************************************************************/

#include "StdAfx.h"
#include "CAISystem.h"

#ifdef CRYAISYSTEM_LOG_AI_ACTORS

#define	AI_OBJECT_LOG_FILE_NAME             "AILog.log"
#define	AI_OBJECT_SECONDARY_LOG_FILE_NAME   "AISignals.csv"

#define	BUFFER_SIZE	256

//
//----------------------------------------------------------------------------------------------
bool CAISystem::CAIActorsLogger::IsLogging(const CAIActor* pAIActor) const
{
	return m_sFile.empty()
		? false
		: pAIActor
		  ? (!strcmp(gAIEnv.CVars.StatsTarget, "all") ||
			   !strcmp(gAIEnv.CVars.StatsTarget, pAIActor->GetName()))
			: false;
}

//
//----------------------------------------------------------------------------------------------
void CAISystem::CAIActorsLogger::LogAIDebugEvent(EAIDebugEvent eAIDebugEvent, const CAIActor* pAIActor, const char* szString) const
{
	if (eAIDebugEvent == eAIDE_Reset)
	{
		Log("\n\n--------------------------------------------------------------------------------------------\n");
		Log("<RESETTING AI SYSTEM>\n");
		Log("aiTick:startTime:<entity> ai_event    details\n");
		Log("--------------------------------------------------------------------------------------------\n");
		// (MATT) Since some gAIEnv settings change only on a reset, this would be the fFrameStartTime to list them {2008/11/20}
		return;
	}
#ifdef CRYAISYSTEM_LOG_AI_ACTORS_SIGNALS
	else if (eAIDebugEvent == eAIDE_SignalExecutedWarning)
	{
		char bufferString[BUFFER_SIZE];
		sprintf(bufferString, "%s\n", szString);
		LogSecondary(bufferString);
		return;
	}
#endif

	if (!pAIActor)
		return;

	// Filter to only log the AI Objects we are interested in
	// I.e. if not "all" and if not our current target, return
	const char* szStatsTarget = gAIEnv.CVars.StatsTarget;
	const char* szAIActorName = pAIActor->GetName();
	if ((strcmp(szStatsTarget, "all")) &&	(strcmp(szStatsTarget, szAIActorName)))
		return;


	const char* szEventString;
	switch (eAIDebugEvent)
	{
	case	eAIDE_SignalReceived:
		szEventString = "signal_received     ";
		break;
	case	eAIDE_AuxSignalReceived:
		szEventString = "aux_signal_received ";
		break;
	case	eAIDE_SignalExecuting:
		szEventString = "signal_executing    ";
		break;
	case	eAIDE_GoalPipeInserted:
		szEventString = "goalpipe_inserted   ";
		break;
	case	eAIDE_GoalPipeSelected:
		szEventString = "goalpipe_selected   ";
		break;
	case	eAIDE_GoalPipeReset:
		szEventString = "goalpipe_reset      ";
		break;
	case	eAIDE_BehaviorSelected:
		szEventString = "behavior_selected   ";
		break;
	case	eAIDE_BehaviorDestructor:
		szEventString = "behavior_destructor ";
		break;
	case	eAIDE_BehaviorConstructor:
		szEventString = "behavior_constructor";
		break;
	case	eAIDE_AttentionTarget:
		szEventString = "att_target_change   ";
		break;
	case	eAIDE_StimulusRegistered:
		szEventString = "stimulus_registered ";
		break;
	case	eAIDE_HandlerEvent:
		szEventString = "handler_event       ";
		break;
	case	eAIDE_ActionStart:
		szEventString = "action_start        ";
		break;
	case	eAIDE_ActionSuspend:
		szEventString = "action_suspend      ";
		break;
	case	eAIDE_ActionResume:
		szEventString = "action_resume       ";
		break;
	case	eAIDE_ActionEnd:
		szEventString = "action_end          ";
		break;
	case	eAIDE_RefPointPos:
		szEventString = "refpoint_pos        ";
		break;
	case	eAIDE_Event:
		szEventString = "triggering event    ";
		break;
	case	eAIDE_LuaComment:
		szEventString = "Lua_comment         ";
		break;
	default:
		szEventString = "undefined           ";
		break;
	}
 
	// Fetch the current AI tick and the time that tick started
	int nAITickCount = GetAISystem()->GetAITickCount();
	float fFrameStartTime = GetAISystem()->GetFrameStartTimeSeconds();

	char bufferString[BUFFER_SIZE];

	if (!szString)
	{
		szString = "<null>";
	}

	sprintf(bufferString, "%6d:%9.3f: <%s> %s\t\t\t%s\n",
		nAITickCount, fFrameStartTime, szAIActorName, szEventString, szString);
	Log(bufferString);
}

//
//----------------------------------------------------------------------------------------------
void CAISystem::CAIActorsLogger::InitFile() const
{
	// Set the string
	m_sFile = gEnv->pSystem->GetRootFolder();
	m_sFile += AI_OBJECT_LOG_FILE_NAME;
	
	// Open to wipe and write any preamble
	FILE* pFile = fxopen(m_sFile.c_str(), "wt");
	fputs("AI Objects debugging log\n", pFile);

	// (MATT) This should help in making clear which log this is
	// localtime appears to be standard - but elsewhere WIN32 is specified - to test on other platforms {2008/11/20}
#ifdef WIN32
	// Get time.
	time_t ltime;
	time(&ltime);
	tm* pTmToday = localtime(&ltime);

	char sz[1024];
	strftime(sz, sizeof sz, "Date(%d %b %Y) Time(%H %M %S)\n\n", pTmToday);		
	fputs(sz, pFile);
#endif

	fclose(pFile);
}

//
//----------------------------------------------------------------------------------------------
void CAISystem::CAIActorsLogger::InitFileSecondary() const
{
	m_sFileSecondary = gEnv->pSystem->GetRootFolder();
	m_sFileSecondary += AI_OBJECT_SECONDARY_LOG_FILE_NAME;

	// Open to wipe and write any preamble
	FILE* pFileSecondary = fxopen(m_sFileSecondary.c_str(), "wt");
	fputs("Function,Time,Page faults,Entity\n", pFileSecondary);
	fclose(pFileSecondary);
}

//----------------------------------------------------------------------------------------------
void CAISystem::CAIActorsLogger::Log(const char* szString) const
{
	if (gAIEnv.CVars.RecordLog)
	{
		GetAISystem()->LogEvent("<AI Objects Logger>", szString);
	}
	else
	{
		if (m_sFile.empty())
		{
			InitFile();
		}

		if (FILE* pFile = fxopen(m_sFile.c_str(), "at"))
		{
			fputs(szString, pFile);
			fclose(pFile);
		}
	}
}

//
//----------------------------------------------------------------------------------------------
void CAISystem::CAIActorsLogger::LogSecondary(const char* szString) const
{
	if (m_sFile.empty())
	{
		InitFileSecondary();
	}

	if (FILE* pFileSecondary = fxopen(m_sFileSecondary.c_str(), "at"))
	{
		fputs(szString, pFileSecondary);
		fclose(pFileSecondary);
	}
}


#endif	// #ifdef CRYAISYSTEM_LOG_AI_ACTORS
